/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.dao;

import org.ipti.br.tag.entity.Organization;
import org.ipti.br.tag.entity.Organization_;
import org.ipti.br.tag.entity.Personage;
import org.ipti.br.tag.entity.Personage_;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.ipti.br.tag.util.EncryptionUtil;

/**
 *
 * @author israel
 */
@Stateless
public class OrganizationFacade extends AbstractFacade<Organization> {

    @PersistenceContext(unitName = "TAG2PU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public OrganizationFacade() {
        super(Organization.class);
    }

    @Override
    public void create(Organization organization) {
        getEntityManager().persist(organization);
    }

    @Override
    public void edit(Organization organization) {
        organization.setSerialNumber(null);

        getEntityManager().merge(organization);
    }

    public void editForSynchronization(Organization organization) {
        getEntityManager().merge(organization);
    }

    public List<Organization> getOrganizationChildren(Long organizationID) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Organization> cq = cb.createQuery(Organization.class);
        Root<Organization> from = cq.from(Organization.class);
        Predicate predicate = cb.equal(from.get(Organization_.org_father).get(Organization_.id), organizationID);
        cq.orderBy(cb.asc(from.get(Organization_.name)));
        cq.where(cb.and(predicate));

        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<Organization> findAllOrder() {
        return findAllOrderBy(Organization_.name);
    }

    public List<Organization> getOrganizationsByName(String organizationName) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Organization> cq = cb.createQuery(Organization.class);
        Root<Organization> root = cq.from(Organization.class);
        cq.where(cb.and(cb.like(cb.upper(root.get(Organization_.name)), "%" + organizationName.toUpperCase() + "%")));
        cq.orderBy(cb.asc(root.get(Organization_.name)));
        return getEntityManager().createQuery(cq).getResultList();
    }

    public Organization getOrganizationByName(String organizationName) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Organization> cq = cb.createQuery(Organization.class);
        Root<Organization> root = cq.from(Organization.class);
        cq.where(cb.and(cb.like(root.get(Organization_.name), organizationName)));

        try {
            return getEntityManager().createQuery(cq).getSingleResult();
        } catch (Exception ex) {
            return null;
        }

    }

    public List<Organization> getOrganizationsByPersonages(List<Long> personagesIDs) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Organization> cq = cb.createQuery(Organization.class);
        Root<Organization> root = cq.from(Organization.class);
        Join<Organization, Personage> personages = root.join(Organization_.personages);
        cq.select(root);

        List<Predicate> personagePredicateList = new ArrayList<Predicate>();
        for (Long l : personagesIDs) {
            personagePredicateList.add(cb.equal(personages.get(Personage_.id), l));
        }

        if (personagePredicateList.isEmpty()) {
            return new ArrayList<Organization>();
        } else if (personagePredicateList.size() == 1) {
            cq.where(personagePredicateList.get(0));
        } else {
            cq.where(cb.or(personagePredicateList.toArray(new Predicate[0])));
        }

        cq.orderBy(cb.asc(root.get(Organization_.name)));
        return getEntityManager().createQuery(cq).getResultList();
    }
}
